﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using Common.Utilities;

namespace Workflows.Components.Rules
{
    /// <summary>
    /// class referred must have an empty constructor and 
    /// be able to created from Activator
    /// and also a public method that accepts an object that 
    /// matches the evaluable obj
    /// </summary>
    public class ClassEvaluator:IEvaluator 
    {
        public event ObjectUpdatedAfterEvaluation OnObjectUpdated;

        #region members
        private object _Evaluable;
        /// <summary></summary>
        public object Evaluable
        {
            get
            {
                return this._Evaluable;
            }
            set
            {
                this._Evaluable = value;
            }
        }

        private string _AssemblyFilePath;
        /// <summary></summary>
        public string AssemblyFilePath
        {
            get
            {
                return this._AssemblyFilePath;
            }
            set
            {
                this._AssemblyFilePath = value;
            }
        }

        private string _ClassFullName;
        /// <summary></summary>
        public string ClassFullName
        {
            get
            {
                return this._ClassFullName;
            }
            set
            {
                this._ClassFullName = value;
            }
        }

        private string _EvaluateMethodName;
        /// <summary></summary>
        public string EvaluateMethodName
        {
            get
            {
                return this._EvaluateMethodName;
            }
            set
            {
                this._EvaluateMethodName = value;
            }
        }
        #endregion

        /// <summary>
        /// constructor
        /// </summary>
        /// <param name="objToEvaluate"></param>
        /// <param name="assemFilePath"></param>
        /// <param name="typeName"></param>
        /// <param name="methodName"></param>
        public ClassEvaluator(object objToEvaluate,string assemFilePath, string typeName, string methodName)
        {
            this._Evaluable = objToEvaluate;
            this._AssemblyFilePath = assemFilePath;
            this._ClassFullName = typeName;
            this._EvaluateMethodName = methodName;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool Evaluate()
        {
            try
            {
                Assembly assem = Assembly.LoadFile(this._AssemblyFilePath);
                object instance = Activator.CreateInstance(assem.GetType(this._ClassFullName));
                object result =
                    instance.GetType().InvokeMember(this._EvaluateMethodName, BindingFlags.InvokeMethod, null, instance,
                                                    new object[] {this._Evaluable});

                return (bool) result;
            }
            catch(Exception ex)
            {
                ExceptionHandler.HandlesException(ex);
                return false;
            }
        }
    }
}
